/*
   file_name :Atomic_operations_and_memory_ordering/load_store.cc
   date_time :2025.07.13
   Comment:
      内存顺序，自旋锁的模拟，原子操作
*/

#include <iostream>
using namespace std;
#include <atomic>
#include <vector>
#include <cassert>
#include <thread>

// atomic_flag 模拟自旋锁
class SpinLock
{
public:
    void lock()
    {
        while (flag.test_and_set(std::memory_order_acquire))
            ; // 自旋等待，直到获取锁
    }

    void unlock()
    {
        flag.clear(std::memory_order_release);
    }

private:
    std::atomic_flag flag = ATOMIC_FLAG_INIT;
};

void TestSpinLock()
{
    SpinLock spinlock;
    std::thread t1([&spinlock]()
                   {
    spinlock.lock();
    for(int i = 0;i<3;i++)
        std::cout<<"*";
    
    std::cout<<std::endl;
    spinlock.unlock(); });

    std::thread t2([&spinlock]()
                   {
    spinlock.lock();
    for(int i = 0;i<3;i++)
        std::cout<<"?";
    std::cout<<std::endl;
    spinlock.unlock(); });

    t1.join();
    t2.join();
}

std::atomic<bool> x1;
std::atomic<bool> y2;
std::atomic<int> z1;

// 基于memory_order_relaxed 在 cpu 层面上，原子存储可能被编译器优化，y可能比x先去执行
void write_x_then_y1()
{
    x1.store(true, std::memory_order_relaxed);
    y2.store(true, std::memory_order_relaxed);
}

void read_y_then_x1()
{
    while (!y2.load(std::memory_order_relaxed))
        std::cout << "y load false" << std::endl;

    if (x1.load(std::memory_order_relaxed))
        ++z1;
    assert(z1.load() != 0);
}

void TestOrderRelaxed1()
{
    x1 = false;
    y2 = false;
    z1 = 0;

    std::thread t1(write_x_then_y1);
    std::thread t2(read_y_then_x1);

    t1.join();
    t2.join();
}

void TestOrderRelaxed2()
{
    std::atomic<int> a{0};
    std::vector<int> v3, v4;

    std::thread t1([&a]()
                   {
        for(int i = 0;i<10;i+=2)
            a.store(i,std::memory_order_relaxed); });

    std::thread t2([&a]()
                   {
        for(int i = 1;i<10;i+=2)
            a.store(i,std::memory_order_relaxed); });

    std::thread t3([&v3, &a]()
                   {
        for(int i = 0;i<10;++i)
            v3.push_back(a.load(std::memory_order_relaxed)); });

    std::thread t4([&v4, &a]()
                   {
        for(int i = 0;i<10;++i)
            v4.push_back(a.load(std::memory_order_relaxed)); });

    cout << "v3: " << endl;
    for (auto &e : v3)
    {
        cout << e << " ";
    }
    cout << endl
         << "v3.size() = " << v3.size() << endl;

    cout << "---------------------------------" << endl;

    cout << "v4: " << endl;
    for (auto &e : v4)
    {
        cout << e << " ";
    }
    cout << endl
         << "v4.size() = " << v4.size() << endl;

    t1.join();
    t2.join();
    t3.join();
    t4.join();
}

std::atomic<bool> x;
std::atomic<bool> y;
std::atomic<int> z;

void write_x_then_y()
{
    // 全局一致性
    x.store(true, std::memory_order_seq_cst);
    y.store(true, std::memory_order_seq_cst);
}

void read_y_then_x()
{
    while (!y.load(std::memory_order_seq_cst))
        std::cout << "y load false" << std::endl;

    if (x.load(std::memory_order_seq_cst))
        ++z;
}

void TestOrderRelaxed()
{
    x = false;
    y = false;
    z = 0;

    std::thread t1(write_x_then_y);
    std::thread t2(read_y_then_x);

    t1.join();
    t2.join();

    assert(z.load() != 0);
}

//         内存顺序	                                  特点
// std::memory_order_seq_cst	顺序一致性（最严格，性能较低，适合默认使用）
// std::memory_order_acquire	获取操作（保证之后的读操作不会被重排到它之前）
// std::memory_order_release	释放操作（保证之前的写操作不会被重排到它之后）
// std::memory_order_relaxed	松散顺序（仅保证原子性，不保证顺序，性能最高，适合计数器等简单场景）

void TestReleaseAcquire()
{
    // a happens before b 只要 a 发生，a发生后的结果就会同步给b 而不是 a 一定在 b 之前执行
    std::atomic<bool> rx, ry;
    std::thread t1([&]()
                   {
        rx.store(true,std::memory_order_relaxed);
        // release 保证之前的写操作不会在我之后
        ry.store(true,std::memory_order_release); });

    std::thread t2([&]()
                   {
        while(!ry.load(std::memory_order_acquire));//保证之后的读操作不会在我之前
        assert(rx.load(std::memory_order_relaxed)); });

    t1.join();
    t2.join();
}

// release只能保证其他线程可见，并不能保证其他线程能够正确读到，正因为如此才引入acquire,而consumer只能保证相关原子能够读到
void ConsumeDependency()
{
    std::atomic<std::string *> ptr;
    int data;

    std::thread t1([&]()
                   {
        std::string* p = new std::string("Hello World");
        data = 42;
        ptr.store(p,std::memory_order_release); });

    std::thread t2([&]()
                   {
        std::string* p2;
        while(!(p2 = ptr.load(std::memory_order_consume)));
        assert(*p2 == "Hello World");
        assert(data == 42); });

    t1.join();
    t2.join();
}

void TestReleaseSequence()
{
    std::vector<int> data;
    std::atomic<int> flag{0};

    std::thread t1([&]()
                   {
        data.push_back(42);
        flag.store(1,std::memory_order_release); });

    std::thread t2([&]
                   {
        int expected = 1;
        //compare_exchange_strong 作用: 如果 flag与expected 不相等返回false
        //如果 flag与expected 相等返回true 且 flag被修改为2
        while(!flag.compare_exchange_strong(expected,2,std::memory_order_relaxed))
            expected = 1; });

    std::thread t3([&]()
                   {
        while(flag.load(std::memory_order_acquire)<2);
        assert(data.at(0) == 42); });

    t1.join();
    t2.join();
    t3.join();
}

int main()
{
    // ConsumeDependency();
    // TestReleaseSequence();

    TestOrderRelaxed1();

    // TestSpinLock();

    // atomic<bool> ab;
    // cout << ab.is_always_lock_free << endl;
    // return 0;
}